package demoMod.invincibleOne.cards.invincible;

import basemod.ReflectionHacks;
import basemod.abstracts.AbstractCardModifier;
import basemod.abstracts.CustomCard;
import basemod.helpers.CardModifierManager;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.g2d.BitmapFont;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.graphics.g2d.TextureAtlas;
import com.evacipated.cardcrawl.modthespire.lib.SpireOverride;
import com.evacipated.cardcrawl.modthespire.lib.SpireSuper;
import com.megacrit.cardcrawl.actions.common.DrawCardAction;
import com.megacrit.cardcrawl.cards.AbstractCard;
import com.megacrit.cardcrawl.cards.CardGroup;
import com.megacrit.cardcrawl.characters.AbstractPlayer;
import com.megacrit.cardcrawl.core.CardCrawlGame;
import com.megacrit.cardcrawl.core.Settings;
import com.megacrit.cardcrawl.dungeons.AbstractDungeon;
import com.megacrit.cardcrawl.helpers.FontHelper;
import com.megacrit.cardcrawl.helpers.ImageMaster;
import com.megacrit.cardcrawl.localization.CardStrings;
import com.megacrit.cardcrawl.monsters.AbstractMonster;
import com.megacrit.cardcrawl.screens.SingleCardViewPopup;
import demoMod.invincibleOne.InvincibleOneMod;
import demoMod.invincibleOne.enums.AbstractCardEnum;
import demoMod.invincibleOne.enums.CardTagsEnum;
import org.lwjgl.Sys;

import java.lang.reflect.InvocationTargetException;
import java.util.Locale;
import java.util.function.Supplier;

public abstract class AbstractInvincibleCard extends CustomCard {
    public static final CardStrings cardStrings = CardCrawlGame.languagePack.getCardStrings(InvincibleOneMod.makeID("AbstractInvincibleCard"));

    protected AbstractCardModifier modifier;

    public int baseM2;
    public int m2;
    public boolean playFirst;

    public AbstractInvincibleCard(String id, String name, String img, int cost, String rawDescription, CardType type, CardRarity rarity, CardTarget target) {
        super(id, name, img, cost, rawDescription, type, AbstractCardEnum.INVINCIBLE, rarity, target);
        this.isMultiDamage = type == CardType.ATTACK && target == CardTarget.ALL_ENEMY;
    }

    @Override
    public void loadCardImage(String img) {
        if (img.contains("/cards/todo")) {
            img += "_" + this.type.name().toLowerCase(Locale.ROOT) + ".png";

            this.textureImg = img;
        }
        super.loadCardImage(img);
    }

    @Override
    public void onRemoveFromMasterDeck() {
        if (modifier != null) {
            CardModifierManager.removeSpecificModifier(this, modifier, true);
        }
    }

    @Override
    public boolean canUse(AbstractPlayer p, AbstractMonster m) {
        return super.canUse(p, m) && !hasTag(CardTagsEnum.VIRUS);
    }

    public abstract Runnable getUpgradeAction();

    protected Supplier<Boolean> getGlowCondition() {
        return () -> false;
    }

    @Override
    public void triggerOnGlowCheck() {
        this.glowColor = AbstractCard.BLUE_BORDER_GLOW_COLOR.cpy();
        if (getGlowCondition().get()) {
            this.glowColor = AbstractCard.GOLD_BORDER_GLOW_COLOR.cpy();
        }
    }

    @Override
    public void triggerWhenDrawn() {
        if (hasTag(CardTagsEnum.VIRUS)) {
            for (AbstractCard card : AbstractDungeon.player.masterDeck.group) {
                if (card instanceof Latency) {
                    // if (((Latency) card).count <= 0) {
                    for (int i=0;i<card.magicNumber;i++) {
                        use(AbstractDungeon.player, null);
                    }
                    // }
                }
            }
            use(AbstractDungeon.player, null);
            addToTop(new DrawCardAction(1));
        }
    }

    @Override
    public void upgrade() {
        if (this.canUpgrade()) {
            this.upgradeName();
            getUpgradeAction().run();
        }
    }

    @Override
    public abstract void use(AbstractPlayer p, AbstractMonster m);

    public void onInitDeck() {}
    public boolean onBattleStart() {
        return false;
    }

    public void atEndOfTurn(CardGroup currGroup) {

    }

    @SpireOverride
    public void renderSkillBg(SpriteBatch sb, float x, float y) {
        if (hasTag(CardTagsEnum.VIRUS)) {
            Color renderColor = ReflectionHacks.getPrivate(this, AbstractCard.class, "renderColor");
            try {
                ReflectionHacks.getCachedMethod(AbstractCard.class, "renderHelper", SpriteBatch.class, Color.class, TextureAtlas.AtlasRegion.class, float.class, float.class)
                                .invoke(this, sb, renderColor, ImageMaster.CARD_SKILL_BG_BLACK, x, y);
            } catch (IllegalAccessException | InvocationTargetException e) {
                throw new RuntimeException(e);
            }
        } else {
            SpireSuper.call(sb, x, y);
        }
    }

    @SpireOverride
    protected void renderType(SpriteBatch sb) {
        if (hasTag(CardTagsEnum.VIRUS)) {
            BitmapFont font = FontHelper.cardTypeFont;
            font.getData().setScale(this.drawScale);
            FontHelper.renderRotatedText(sb, font, cardStrings.EXTENDED_DESCRIPTION[0], this.current_x, this.current_y - 22.0F * this.drawScale * Settings.scale, 0.0F, -1.0F * this.drawScale * Settings.scale, this.angle, false, Color.DARK_GRAY);
        } else {
            SpireSuper.call(sb);
        }
    }

    public void renderLegendaryText(SpriteBatch sb, float xPos, float yPos, float yOffsetBase, float scale) {
        if (this.isFlipped || this.isLocked || this.transparency <= 0.0F)
            return;
        BitmapFont font = FontHelper.cardTitleFont;
        float offsetY = yOffsetBase * Settings.scale * scale / 2.0F;
        BitmapFont.BitmapFontData fontData = font.getData();
        float originalScale = fontData.scaleX;
        float scaleMulti = 0.8F;
        fontData.setScale(scaleMulti * scale * 0.85F);
        Color color =Settings.RED_TEXT_COLOR.cpy();
        color.a = this.transparency;
        FontHelper.renderRotatedText(sb, font, cardStrings.EXTENDED_DESCRIPTION[1], xPos, yPos, 0.0F, offsetY, this.angle, true, color);
        fontData.setScale(originalScale);
    }

    @SpireOverride
    protected void renderAttackPortrait(SpriteBatch sb, float x, float y) {
        CardRarity tmp = this.rarity;
        if (this.rarity == AbstractCardEnum.LEGENDARY) {
            this.rarity = CardRarity.RARE;
        }
        SpireSuper.call(sb, x, y);
        this.rarity = tmp;
    }

    @SpireOverride
    protected void renderSkillPortrait(SpriteBatch sb, float x, float y) {
        CardRarity tmp = this.rarity;
        if (this.rarity == AbstractCardEnum.LEGENDARY) {
            this.rarity = CardRarity.RARE;
        }
        SpireSuper.call(sb, x, y);
        this.rarity = tmp;
    }

    @SpireOverride
    protected void renderPowerPortrait(SpriteBatch sb, float x, float y) {
        CardRarity tmp = this.rarity;
        if (this.rarity == AbstractCardEnum.LEGENDARY) {
            this.rarity = CardRarity.RARE;
        }
        SpireSuper.call(sb, x, y);
        this.rarity = tmp;
    }

    @SpireOverride
    protected void renderDynamicFrame(SpriteBatch sb, float x, float y, float typeOffset, float typeWidth) {
        CardRarity tmp = this.rarity;
        if (this.rarity == AbstractCardEnum.LEGENDARY) {
            this.rarity = CardRarity.RARE;
        }
        SpireSuper.call(sb, x, y, typeOffset, typeWidth);
        this.rarity = tmp;
    }

    @SpireOverride
    protected void renderBannerImage(SpriteBatch sb, float drawX, float drawY) {
        CardRarity tmp = this.rarity;
        if (this.rarity == AbstractCardEnum.LEGENDARY) {
            this.rarity = CardRarity.RARE;
        }
        SpireSuper.call(sb, drawX, drawY);
        this.rarity = tmp;
    }

    public void render(SpriteBatch sb) {
        super.render(sb);
        if (rarity == AbstractCardEnum.LEGENDARY) {
            renderLegendaryText(sb, this.current_x, this.current_y, 400.0F, this.drawScale);
        }
    }

    public void renderInLibrary(SpriteBatch sb) {
        super.renderInLibrary(sb);
        if (rarity == AbstractCardEnum.LEGENDARY) {
            renderLegendaryText(sb, this.current_x, this.current_y, 400.0F, this.drawScale);
        }
    }
}
